import java.io.ByteArrayOutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNLogEntryPath;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.io.*;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

public class SVNManager {

	public static void main(String[] args) throws SVNException {

		DAVRepositoryFactory.setup();

		String url = "https://pio.svn.sourceforge.net/svnroot/pio";
		String name = "anonymous";
		String password = "anonymous";
		long startRevision = 0;
		long endRevision = -1; // HEAD (the latest) revision
		int numEntries = 0;	//Number of repository revision entries covered. 

		SVNRepository repository = null;

		try {
			repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));	//Create repository
			ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password); //create authentication manager (not always necessary)
			repository.setAuthenticationManager(authManager); 

			Collection logEntries = null;

			logEntries = repository.log(new String[] { "" }, null, startRevision, endRevision, true, true); //Check all log entries in the repository
			
			//For the first 6 entries (5 pairs of entries)
			for (Iterator entries = logEntries.iterator(); entries.hasNext();) {
				if (numEntries < 6) {
					numEntries++;
					SVNLogEntry logEntry = (SVNLogEntry) entries.next();
					System.out.println("---------------------------------------------");
					System.out.println("revision: " + logEntry.getRevision());
					System.out.println("author: " + logEntry.getAuthor());
					System.out.println("date: " + logEntry.getDate());
					System.out.println("log message: " + logEntry.getMessage());
					
					//If any changes were made to files
					if (logEntry.getChangedPaths().size() > 0) {
						System.out.println();
						System.out.println("changed paths:");
						Set changedPathsSet = logEntry.getChangedPaths()
								.keySet();

						int nFilesAdded = 0;
						int nFilesModified = 0;
						int nFilesDeleted = 0;
						int totalLinesOfCodeInChangedFiles = 0;
						
						//For each changed file/folder
						for (Iterator changedPaths = changedPathsSet.iterator(); changedPaths.hasNext();) {

							SVNLogEntryPath entryPath = (SVNLogEntryPath) logEntry
									.getChangedPaths().get(changedPaths.next());
							SVNNodeKind nodeKind = repository
									.checkPath(entryPath.getPath(),
											logEntry.getRevision());

							//If it is a file/missing node
							if (nodeKind == SVNNodeKind.FILE || nodeKind == SVNNodeKind.NONE) {
								if (entryPath.getType() == 'A') { // File added
									nFilesAdded++;
									totalLinesOfCodeInChangedFiles += returnNumNewLinesInFile(repository, entryPath, logEntry);
								} else if (entryPath.getType() == 'M') { // Modified
									nFilesModified++;
									totalLinesOfCodeInChangedFiles += returnNumNewLinesInFile(repository, entryPath, logEntry);
								} else if (entryPath.getType() == 'D') { // Deleted
									nFilesDeleted++;
								}
							}
						}
						System.out.println("Files Added: " + nFilesAdded);
						System.out.println("Files Modified: " + nFilesModified);
						System.out.println("Files Deleted: " + nFilesDeleted);
						System.out.println("Total Lines of Code: " + totalLinesOfCodeInChangedFiles);
						System.out.println();
					}
				} else {
					break;
				}
			}
		} finally {
		}
	}

	/**
	 * Count the number of lines in the file of this log entry. 
	 * 
	 * @param repository
	 * The repository
	 * @param entryPath
	 * The entry path of the log entry
	 * @param logEntry
	 * The log entry of the file
	 * @return
	 * The number of newlines in the file. 
	 * @throws SVNException
	 */
	public static int returnNumNewLinesInFile(SVNRepository repository, SVNLogEntryPath entryPath, SVNLogEntry logEntry) throws SVNException {
		int nNewlines = 0;
		SVNProperties fileProperties = new SVNProperties();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		repository.getFile(entryPath.getPath(), logEntry.getRevision(), fileProperties, baos);
		
		byte byteArray[] = baos.toByteArray();
		for(int i = 0; i < byteArray.length; i++)
			if(byteArray[i] == '\n')
				nNewlines++;
		return nNewlines;
	}
}
